#pragma once

#include "Point.h"
#include <algorithm>

using namespace std;

namespace model
{
class Line
{
  public:
	
	Line(){}
	Line(Point start, Point end)
	{ 
		this->start = start; 
		this->end = end;		
		calculateCoeficients();
	}
	
	virtual ~Line(){}

	void setStartAndEnd(Point start, Point end) 
	{ 
		this->start = start; 
		this->end = end;
		calculateCoeficients();
	}
	
	double determinant(const Line &line) const
	{
		return (a*line.b - line.a*b);
	}

	bool isParallel(const Line &line) const
	{
		return (determinant(line)==0);
	}
	
	Point intersection(const Line &line)
	{
		Point intersect(-1, -1);
		
		if (!isParallel(line))
		{
			double det = determinant(line);
			intersect.setX((line.b*c - b*line.c)/det);
			intersect.setY((a*line.c - line.a*c)/det);
		}
		
		return intersect;
	}

	bool intersectsWith(const Line &line) const
	{
		return !isParallel(line);
	}

	bool intersectsInSegmentWith(const Line &line)
	{
		Point intersectionPoint = intersection(line);
		return containsPoint(intersectionPoint) && line.containsPoint(intersectionPoint);
	}
	
	bool containsPoint(const Point &point) const
	{/*
		bool extremoIzq      = min(start.x(), end.x()) < point.x();
		bool extremoDerecho  = max(start.x(), end.x()) > point.x();
		bool extremoSuperior = min(start.y(), end.y()) < point.y();
		bool extremoInferior = max(start.y(), end.y()) > point.y();

		return extremoIzq && extremoDerecho && extremoSuperior && extremoInferior;
		*/
		return (min(start.x(), end.x()) < point.x()) && (max(start.x(), end.x()) > point.x()) && (min(start.y(), end.y()) < point.y()) && (max(start.y(), end.y()) > point.y());
	}
	
  protected:

	void calculateCoeficients()
	{
		a = end.y() - start.y();
		b = start.x() - end.x();
		c = a*start.x() + b*start.y();
	}

	
	Point  start, end;
	double a, b, c;	
};
};